package com.kmxd.ams.app.arrange.command;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.common.collect.Lists;
import com.kmxd.ams.client.archive.IArchiveFieldSvc;
import com.kmxd.ams.client.archive.vo.ArchiveFieldListVO;
import com.kmxd.ams.core.common.bo.ConditionBO;
import com.kmxd.ams.core.common.enums.*;
import com.kmxd.ams.core.config.AmsConfig;
import com.kmxd.ams.infra.arrange.entity.Document;
import com.kmxd.ams.infra.arrange.entity.Volume;
import java.util.*;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 高级查询条件处理
 *
 * @author zuolg
 */
@Slf4j
@Component
@AllArgsConstructor
public class AdvancedQueryCmd {
  private final IArchiveFieldSvc archiveFieldSvc;
  private AmsConfig amsConfig;

  List<String> ignore_field = Lists.newArrayList("filling_date", "doc_date");

  /**
   * 获取文件级高级查询sql
   *
   * @param req
   * @return
   */
  public String getDocQuerySql(Document req) {
    if (StrUtil.isBlank(req.getFilterCondition())
        || !JSONUtil.isTypeJSON(req.getFilterCondition())) {
      return null;
    }

    // 获取所有的字段
    List<ArchiveFieldListVO> fieldDb = archiveFieldSvc.selectListAll();
    // 过滤出属于当前表的字段
    List<ArchiveFieldListVO> fields =
        fieldDb.stream()
            .filter(
                x ->
                    ObjectUtil.equals(x.getTableId(), req.getTableId())
                        && BooleanUtil.isTrue(x.getAttrList())
                        && !ignore_field.contains(x.getDbFieldKey()))
            .collect(Collectors.toList());
    // 构建查询条件
    List<ConditionBO> conditions = JSONUtil.toList(req.getFilterCondition(), ConditionBO.class);
    boolean isMysql =
        StrUtil.isBlank(amsConfig.getDbType())
            || StrUtil.equals(DbTypeEnum.MYSQL.getCode(), amsConfig.getDbType());
    // 构建查询字符串
    return getQueryStr(conditions, fields, isMysql);
  }

  /**
   * 获取特殊查询字符串
   *
   * @param conditions
   * @param fields
   * @param isMysql
   * @return
   */
  public static String getQueryStr(
      List<ConditionBO> conditions, List<ArchiveFieldListVO> fields, boolean isMysql) {
    if (conditions.isEmpty()) {
      return null;
    }
    StringBuilder sb = new StringBuilder();
    if (!conditions.isEmpty()) {
      // 最外层括号
      sb.append("(");
    }
    for (ConditionBO item : conditions) {
      item.setValue(
          ObjectUtil.isNotEmpty(item.getOperator())
                  && (ObjectUtil.equals(item.getOperator().getCode(), OperatorEnum.LIKE.getCode())
                      || ObjectUtil.equals(
                          item.getOperator().getCode(), OperatorEnum.NOT_LIKE.getCode()))
              ? StrUtil.format("'%{}%'", item.getValue())
              : StrUtil.format("'{}'", item.getValue()));

      // 需要特殊处理 -- anyMatch
      if (StrUtil.equals("anyMatch", item.getKey())) {
        List<String> sqls = Lists.newArrayList();
        for (ArchiveFieldListVO field : fields) {
          if (ObjectUtil.equals(item.getOperator().getCode(), OperatorEnum.LIKE.getCode())) {
            sqls.add(StrUtil.format(" {} like {} ", field.getDbFieldKey(), item.getValue().trim()));
          } else {
            sqls.add(StrUtil.format(" {} = {} ", field.getDbFieldKey(), item.getValue().trim()));
          }
        }
        if (!sqls.isEmpty()) {
          sb.append("(");
          sb.append(StrUtil.join(" OR ", sqls));
          sb.append(")");
        }
      } else if (StrUtil.isNotBlank(item.getLogic())) {
        sb.append(StrUtil.format(" {} ", item.getLogic().toUpperCase()));
      } else {
        if (ObjectUtil.isNotEmpty(item.getOperator())) {
          // 重新设置key 等于非驼峰
          item.setKey(StringUtils.camelToUnderline(item.getKey()));
          switch (item.getOperator()) {
              // 等于
            case EQ:
              sb.append(StrUtil.format(" {} = {} ", item.getKey(), item.getValue().trim()));
              break;
              // 不等于
            case NOT_EQ:
              sb.append(StrUtil.format(" {} != {} ", item.getKey(), item.getValue().trim()));
              break;
              // 大于
            case GE:
              sb.append(StrUtil.format(" {} > {} ", item.getKey(), item.getValue().trim()));
              break;
              // 大于等于
            case GE_EQ:
              sb.append(StrUtil.format(" {} >= {} ", item.getKey(), item.getValue().trim()));
              break;
              // 小于
            case LE:
              sb.append(StrUtil.format(" {} < {} ", item.getKey(), item.getValue().trim()));
              break;
              // 小于等于
            case LE_EQ:
              sb.append(StrUtil.format(" {} <= {} ", item.getKey(), item.getValue().trim()));
              break;
              // 包含
            case LIKE:
              sb.append(StrUtil.format(" {} like {} ", item.getKey(), item.getValue().trim()));
              break;
              // 不包含
            case NOT_LIKE:
              sb.append(StrUtil.format(" {} not like {} ", item.getKey(), item.getValue().trim()));
              break;
              // 为空,兼容空字符串
            case EMPTY:
              sb.append(StrUtil.format(" ({} IS NULL OR {} = '') ", item.getKey(), item.getKey()));
              break;
              // 不为空
            case NOT_EMPTY:
              sb.append(
                  StrUtil.format(" ({} IS NOT NULL OR {} != '') ", item.getKey(), item.getKey()));
              break;
            default:
              break;
          }
        }
      }
    }
    if (!conditions.isEmpty()) {
      // 最外层括号
      sb.append(")");
    }
    return sb.toString();
  }

  /**
   * 获取案卷级高级查询sql
   *
   * @param req
   * @return
   */
  public String getVolQuerySql(Volume req) {
    if (StrUtil.isBlank(req.getFilterCondition())
        || !JSONUtil.isTypeJSON(req.getFilterCondition())) {
      return null;
    }
    List<ArchiveFieldListVO> fieldDb = archiveFieldSvc.selectListAll();
    List<ArchiveFieldListVO> fields =
        fieldDb.stream()
            .filter(
                x ->
                    ObjectUtil.equals(x.getTableId(), req.getTableId())
                        && BooleanUtil.isTrue(x.getAttrList())
                        && !ignore_field.contains(x.getDbFieldKey()))
            .collect(Collectors.toList());
    List<ConditionBO> conditions = JSONUtil.toList(req.getFilterCondition(), ConditionBO.class);
    boolean isMysql =
        StrUtil.isBlank(amsConfig.getDbType())
            || StrUtil.equals(DbTypeEnum.MYSQL.getCode(), amsConfig.getDbType());
    return getQueryStr(conditions, fields, isMysql);
  }

  public static void main(String[] args) {
    String json = "[{\"key\":\"anyMatch\",\"operator\":\"like\",\"value\":\"1212\"}]";
    List<ConditionBO> conditions = JSONUtil.toList(json, ConditionBO.class);
    List<ArchiveFieldListVO> fields = Lists.newArrayList();
    ArchiveFieldListVO title = new ArchiveFieldListVO();
    title.setDbFieldKey("title");
    fields.add(title);
    boolean isMysql = true;
    String sql = getQueryStr(conditions, fields, isMysql);
    log.info("sql=" + sql);
  }
}
